package com.qianfeng.es.index;


//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼            BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  


import com.fasterxml.jackson.databind.ObjectMapper;
import com.qianfeng.es.pojo.SmsIndex;
import com.qianfeng.es.utils.ESClient;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.range.ParsedRange;
import org.elasticsearch.search.aggregations.metrics.*;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;

import java.io.IOException;
import java.util.*;

/**
 * Created by jackiechan on 2021/10/29 15:27
 *
 * @author jackiechan
 * @version 1.0
 * //TODO 给最美丽的芳姐介绍学生
 * @since 1.0
 */

public class DocService {
    private String index = "sms-logs-index";
    private ObjectMapper objectMapper = new ObjectMapper();


    public void addDoc(String id) throws IOException {
        RestHighLevelClient client = ESClient.getClient();
        SmsIndex smsIndex = new SmsIndex();
        smsIndex.setCorpName("qianfeng");
        smsIndex.setFee(11);
        smsIndex.setCreateDate(new Date());
        smsIndex.setMobile("13301180781");
        smsIndex.setLongCode("12345");
        smsIndex.setProvince("山东asdasdasd");
        smsIndex.setState(1);
        smsIndex.setSendDate(new Date());
        String json = objectMapper.writeValueAsString(smsIndex);
        //创建请求,并指定 json 数据
        IndexRequest request = new IndexRequest(index).source(json, XContentType.JSON);
        if (id != null) {
            request.id(id);
        }
        IndexResponse response = client.index(request, RequestOptions.DEFAULT);
        System.err.println(response);
    }


    public void get(String id) throws IOException {
        RestHighLevelClient client = ESClient.getClient();
        GetRequest getRequest = new GetRequest(index).id(id);//zwv5ynwBJbTDI88bqNUd
        GetResponse response = client.get(getRequest, RequestOptions.DEFAULT);
        System.err.println(response);
    }


    public void delete(String id) throws IOException {
        RestHighLevelClient client = ESClient.getClient();
        DeleteRequest deleteRequest = new DeleteRequest(index, id);
        DeleteResponse delete = client.delete(deleteRequest, RequestOptions.DEFAULT);
        System.err.println(delete);

    }


    public void update(String id) throws IOException {
        RestHighLevelClient client = ESClient.getClient();
        Map map = new HashMap<>();
        map.put("province", "昌平区");
        String json = objectMapper.writeValueAsString(map);
        UpdateRequest request = new UpdateRequest(index, id).doc(json, XContentType.JSON);
        UpdateResponse response = client.update(request, RequestOptions.DEFAULT);

    }


    public void termQuery(String field,String value) throws IOException {
//        RestHighLevelClient client = ESClient.getClient();
//        SearchRequest searchRequest = new SearchRequest();
//
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//创建封装查询的 builder
//        searchSourceBuilder.query(QueryBuilders.termQuery(field, value));//给 builder 设置查询的方式
//        searchRequest.source(searchSourceBuilder);//给搜索的请求设置查询条件
//
//        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
//        System.err.println(response);
        baseQuery(QueryBuilders.termQuery(field, value));
    }


    public void termsQuery(String field,String... value) throws IOException {
//        RestHighLevelClient client = ESClient.getClient();
//        SearchRequest searchRequest = new SearchRequest();
//
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//创建封装查询的 builder
//        searchSourceBuilder.query(QueryBuilders.termsQuery(field, value));//给 builder 设置查询的方式
//        searchRequest.source(searchSourceBuilder);//给搜索的请求设置查询条件
//
//        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
//        System.err.println(response);
        baseQuery(QueryBuilders.termsQuery(field, value));
    }


    public void matchQuery(String field,String value) throws IOException {
//        RestHighLevelClient client = ESClient.getClient();
//        SearchRequest searchRequest = new SearchRequest();
//
//        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//创建封装查询的 builder
//        searchSourceBuilder.query(QueryBuilders.matchQuery(field, value));//给 builder 设置查询的方式
//        searchRequest.source(searchSourceBuilder);//给搜索的请求设置查询条件
//
//        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
//        System.err.println(response);
        baseQuery(QueryBuilders.matchQuery(field, value));
    }


    public void matchAll() throws IOException {
        baseQuery(QueryBuilders.matchAllQuery());
    }

    public void matchBool(String field,String value) throws IOException {
        baseQuery(QueryBuilders.matchQuery(field,value).operator(Operator.AND));
    }

    public void multi_match(String value,String... field) throws IOException {
        baseQuery(QueryBuilders.multiMatchQuery(value,field));
    }


    public void idsQuery(String ...ids) throws IOException {
        baseQuery(QueryBuilders.idsQuery().addIds(ids));
    }

    public void prefixQuery(String field,String value) throws IOException {
        baseQuery(QueryBuilders.prefixQuery(field, value));
    }

    public void fuzzyQuery(String field,String value) throws IOException {
        baseQuery(QueryBuilders.fuzzyQuery(field, value).prefixLength(2));
    }

    public void wildcardQuery(String field,String value) throws IOException {
        baseQuery(QueryBuilders.wildcardQuery(field, value));
    }

    public void rangeQuery(String field,String from,String to) throws IOException {
        baseQuery(QueryBuilders.rangeQuery(field).gt(from).lt(to));
    }

    public void boolQuery() throws IOException {

        BoolQueryBuilder builder = QueryBuilders.boolQuery().should(QueryBuilders.termQuery("province", "武汉")).should(QueryBuilders.termQuery("province", "北京"))
                .must(QueryBuilders.matchQuery("smsContent", "中国")).must(QueryBuilders.matchQuery("smsContent", "平安"))
                .mustNot(QueryBuilders.termQuery("operatorId", 2));
        baseQuery(builder);

    }


    public void boostQuery() throws IOException {

        BoostingQueryBuilder queryBuilder = QueryBuilders.boostingQuery(QueryBuilders.matchQuery("smsContent", "收货安装"), QueryBuilders.matchQuery("smsContent", "王五"))
                .negativeBoost(0.1f);
        baseQuery(queryBuilder);
    }


    public void hight(String field, String value, String hlFiled) throws IOException {
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery(field, value);
        HighlightBuilder highlightBuilder = new HighlightBuilder().field(hlFiled, 0).preTags("<font color='red'>").postTags("</font>");//创建高亮的查询, 指定返回结果哪个列高亮
//        RestHighLevelClient client = ESClient.getClient();
//        SearchRequest searchRequest = new SearchRequest(index);

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//创建封装查询的 builder
        searchSourceBuilder.query(matchQuery);//给 builder 设置查询的方式
        searchSourceBuilder.highlighter(highlightBuilder);//设置高亮的查询
//        searchRequest.source(searchSourceBuilder);//给搜索的请求设置查询条件

//        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchResponse response = baseQuery(searchSourceBuilder);
        SearchHit[] searchHits = response.getHits().getHits();
        List<Map> allDatas = new ArrayList<>();
        for (SearchHit hit : searchHits) {
            Map<String, Object> map = hit.getSourceAsMap();//将每一条数据的 json 解析到 map 中,json 的 key 就是 map 的 key
           // System.err.println(map);
            HighlightField highlightField = hit.getHighlightFields().get(hlFiled);//获取指定字段的高亮数据
            if (highlightField != null) {
                //System.err.println(highlightField);
                Text[] fragments = highlightField.getFragments();
                if (fragments != null) {
                   // System.err.println(fragments[0].string());
                    map.put(hlFiled,fragments[0].string());//将高亮的数据替换掉原先 map 中的数据
                }
            }
           // System.err.println(map);
            allDatas.add(map);
        }

        System.err.println(allDatas);
    }



    public void cardinalityAgg(String filed,String bieming) throws IOException {
        //设置聚合函数, 注意聚合函数中的 name 是别名
        SearchResponse response = baseAgg(AggregationBuilders.cardinality(bieming).field(filed));
        ParsedCardinality aggregation = response.getAggregations().get(bieming);//获取我们制定的字段的聚合
        System.err.println(aggregation);
        System.err.println(aggregation.getValue());

    }

    public void AvgAggress(String filed,String bieming) throws IOException {

        //设置聚合函数, 注意聚合函数中的 name 是别名
        SearchResponse response = baseAgg(AggregationBuilders.avg(bieming).field(filed));
        ParsedAvg aggregation = response.getAggregations().get(bieming);
        System.err.println(aggregation.getValue());
    }

    public void minAggress(String filed,String bieming) throws IOException {

        //设置聚合函数, 注意聚合函数中的 name 是别名
        SearchResponse response = baseAgg(AggregationBuilders.min(bieming).field(filed));
        ParsedMin aggregation = response.getAggregations().get(bieming);
        System.err.println(aggregation.getValue());
    }
    public void maxAggress(String filed,String bieming) throws IOException {

        //设置聚合函数, 注意聚合函数中的 name 是别名
        SearchResponse response = baseAgg(AggregationBuilders.max(bieming).field(filed));
        ParsedMax aggregation = response.getAggregations().get(bieming);
        System.err.println(aggregation.getValue());
    }

    public void extended_statsAggress(String filed,String bieming) throws IOException {
        //设置聚合函数, 注意聚合函数中的 name 是别名
        SearchResponse response = baseAgg(AggregationBuilders.extendedStats(bieming).field(filed));
        ParsedExtendedStats aggregation = response.getAggregations().get(bieming);
        System.err.println(aggregation.getMax());
        System.err.println(aggregation.getAvg());
    }

    public void rangeAgree(String filed,String bieming) throws IOException {
        //设置聚合函数, 注意聚合函数中的 name 是别名
        SearchResponse response = baseAgg(AggregationBuilders.range(bieming).field(filed).addUnboundedTo(5).addUnboundedFrom(10).addRange(5,10));
        ParsedRange aggregation = response.getAggregations().get(bieming);
        System.err.println(aggregation);
        aggregation.getBuckets().forEach(bucket -> {
            System.err.println(bucket.getDocCount());
        });

    }


    public SearchResponse baseAgg(AggregationBuilder builder) throws IOException {

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //设置聚合函数, 注意聚合函数中的 name 是别名
        searchSourceBuilder.aggregation(builder);
        SearchResponse response = baseQuery(searchSourceBuilder);
        return response;

    }


    public void deleteByQuery(String field,String from,String to) throws IOException {
        RestHighLevelClient client = ESClient.getClient();

        DeleteByQueryRequest request = new DeleteByQueryRequest().setQuery(QueryBuilders.rangeQuery(field).gt(from).lt(to));
        client.deleteByQuery(request,RequestOptions.DEFAULT);
    }


    public SearchResponse baseQuery(QueryBuilder queryBuilder) throws IOException {

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//创建封装查询的 builder
        searchSourceBuilder.query(queryBuilder);//给 builder 设置查询的方式
        SearchResponse response = baseQuery(searchSourceBuilder);
        return response;
    }

    public SearchResponse baseQuery(SearchSourceBuilder searchSourceBuilder) throws IOException {
        RestHighLevelClient client = ESClient.getClient();
        SearchRequest searchRequest = new SearchRequest(index);

        searchRequest.source(searchSourceBuilder);//给搜索的请求设置查询条件
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        System.err.println(response);
        return response;
    }
}